package com.example.airkiss;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.airkiss.utils.HttpConnection;
import com.example.airkiss.utils.WXConstants;
import com.example.airkiss.utils.wxpay.WXPay;
import com.example.airkiss.utils.wxpay.WXPayConstants;
import com.example.airkiss.utils.wxpay.WXPayUtil;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import weixin.popular.api.PayMchAPI;
import weixin.popular.bean.paymch.MchPayApp;
import weixin.popular.bean.paymch.Unifiedorder;
import weixin.popular.bean.paymch.UnifiedorderResult;
import weixin.popular.util.PayUtil;
import weixin.popular.util.XMLConverUtil;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.*;

@Controller
@RequestMapping("/order")
public class OrderController {
    private static Logger LOGGER= LoggerFactory.getLogger(OrderController.class);

    /**
     * 公众号微信登录授权
     * @param request
     * @param response http://2zs8zk.natappfree.cc/wx/wxLogin
     * @return
     * @throws ParseException
     * @author  lbh
     * @date 创建时间：2018年1月18日 下午7:33:59
     * @parameter
     */
    @RequestMapping(value = "/wxLogin", method = RequestMethod.GET)
    public void wxLogin(HttpServletRequest request,
                        HttpServletResponse response)
            throws ParseException, IOException {
        //这个url的域名必须要再公众号中进行注册验证，这个地址是成功后的回调地址
        String backUrl="http://wangyulovezj2018.natapp1.cc/order/callBack";
        // 第一步：用户同意授权，获取code
        String url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+WXConstants.WX_APPID
                + "&redirect_uri="+URLEncoder.encode(backUrl,"UTF-8")
                + "&response_type=code"
                + "&scope=snsapi_userinfo"
                + "&state=STATE#wechat_redirect";

        LOGGER.info("forward重定向地址{" + url + "}");
        //response.sendRedirect(url);
//        return "redirect:"+url;//必须重定向，否则不能成功
        response.sendRedirect(url);
    }

    Map<String,String> open_id = new HashMap<>();
    /**
     * 公众号微信登录授权回调函数
     * @param
     * @param req
     * @return
     * @throws ServletException
     * @throws IOException
     * @author  lbh
     * @date 创建时间：2018年1月18日 下午7:33:53
     * @parameter
     */
    @RequestMapping(value = "/callBack", method = RequestMethod.GET)
    public String callBack(Model model, HttpServletRequest req, HttpServletResponse response) throws Exception {
        System.err.println("获取当前请去的上一个请求："+ req         .getHeader("Referer"));


        /*
         * start 获取微信用户基本信息
         */
        String code =req.getParameter("code");
        //第二步：通过code换取网页授权access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+WXConstants.WX_APPID
                + "&secret="+WXConstants.WX_APPSECRET
                + "&code="+code
                + "&grant_type=authorization_code";

        LOGGER.info("url:"+url);
        JSONObject jsonObject = HttpConnection.doGetJson(url);
        String openid = jsonObject.getString("openid");
        String access_token = jsonObject.getString("access_token");
        String refresh_token = jsonObject.getString("refresh_token");
        //第五步验证access_token是否失效；展示都不需要
        String chickUrl="https://api.weixin.qq.com/sns/auth?access_token="+access_token+"&openid="+openid;

        JSONObject chickuserInfo = HttpConnection.doGetJson(chickUrl);
        LOGGER.info(chickuserInfo.toString());
        if(!"0".equals(chickuserInfo.getString("errcode"))){
            // 第三步：刷新access_token（如果需要）-----暂时没有使用,参考文档https://mp.weixin.qq.com/wiki，
            String refreshTokenUrl="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+openid+"&grant_type=refresh_token&refresh_token="+refresh_token;

            JSONObject refreshInfo = HttpConnection.doGetJson(chickUrl);

            LOGGER.info(refreshInfo.toString());
            access_token=refreshInfo.getString("access_token");
        }

        // 第四步：拉取用户信息(需scope为 snsapi_userinfo)
        String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token
                + "&openid="+openid
                + "&lang=zh_CN";
        LOGGER.info("infoUrl:"+infoUrl);
        JSONObject userInfo = HttpConnection.doGetJson(infoUrl);
        LOGGER.info("JSON-----"+userInfo.toString());
        LOGGER.info("openID-----"+userInfo.getString("openid"));
        LOGGER.info("名字-----"+userInfo.getString("nickname"));
        LOGGER.info("头像-----"+userInfo.getString("headimgurl"));
        HttpSession session = req.getSession();
        session.setAttribute("openID",userInfo.getString("openid"));
        open_id.put("open_id",userInfo.getString("openid"));

        //TODO 微信退款


        Unifiedorder unifiedorder = new Unifiedorder();


        /** APPID */
        unifiedorder.setAppid(WXConstants.WX_APPID);

        /** 商户号 */
        unifiedorder.setMch_id(WXConstants.MCH_ID);

        /** 随机字符串 */
        unifiedorder.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));

        /** 商品描述 */
        unifiedorder.setBody("买水了");

        /** 商户订单号 */
        unifiedorder.setOut_trade_no("wy"+System.currentTimeMillis());

        /** 订单总金额 */
        unifiedorder.setTotal_fee("1");   // 订单总金额,单位为分;

        /** 用户端请求IP地址 */
        unifiedorder.setSpbill_create_ip(getIpAddr(req));

        /** 异步通知回调地址 */
        unifiedorder.setNotify_url(WXConstants.NOTIFY_URL);

        /** 交易类型 */
        unifiedorder.setTrade_type("JSAPI");

        System.err.println();
        unifiedorder.setOpenid(userInfo.getString("openid"));
        System.err.println("获取到的OPENID："+userInfo.getString("openid"));

        LOGGER.warn("微信APP支付--(签名前):" + XMLConverUtil.convertToXML(unifiedorder));

        /** 获取签名 */
        UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, WXConstants.KEY);

        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_code):" + unifiedorderResult.getReturn_code());
        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_msg):" + unifiedorderResult.getReturn_msg());
        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(result_code):" + unifiedorderResult.getResult_code());
        LOGGER.warn("微信APP支付--支付请求参数封装(签名后):" + XMLConverUtil.convertToXML(unifiedorder));
        LOGGER.warn("微信APP支付--支付统一下单接口返回数据:" + new Gson().toJson(unifiedorderResult));

        // 下单结果验签;
        if(unifiedorderResult.getSign_status() != null && unifiedorderResult.getSign_status()) {
            LOGGER.warn("微信APP支付验签成功");
            MchPayApp mchPayApp = PayUtil.generateMchAppData(unifiedorderResult.getPrepay_id(), WXConstants.WX_APPID,
                    WXConstants.MCH_ID, WXConstants.KEY);

            String appId = mchPayApp.getAppid();//微信公众号AppId
            String timeStamp = WXPayUtil.getCurrentTimestamp()+"";//当前时间戳
            String prepayId = "prepay_id="+mchPayApp.getPrepayid();//统一下单返回的预支付id
            String nonceStr = WXPayUtil.generateNonceStr();//不长于32位的随机字符串
            Map<String,String> signMap = new TreeMap<>();//自然升序map
            signMap.put("appId",appId);
            signMap.put("package",prepayId);
            signMap.put("timeStamp",timeStamp);
            signMap.put("nonceStr",nonceStr);
            signMap.put("signType","MD5");
            model.addAttribute("appId",appId);
            model.addAttribute("timeStamp",timeStamp);
            model.addAttribute("nonceStr",nonceStr);
            model.addAttribute("prepayId",prepayId);
            String paySign = WXPayUtil.generateSignature(signMap, WXConstants.KEY);
            model.addAttribute("paySign",paySign);//获取签名
            System.err.println("返回的参数:"+JSON.toJSONString(signMap));
        }


//
//        //组装微信公众号支付参数
//
//        Map<String,String> packageParams = new TreeMap<>();
//        packageParams.put("appid", WXConstants.WX_APPID);
//        packageParams.put("body", "卖水啦!便宜啦!");
//        packageParams.put("mch_id", WXConstants.MCH_ID);
//        packageParams.put("nonce_str", WXPayUtil.generateNonceStr());
//        packageParams.put("notify_url", WXConstants.NOTIFY_URL);
//        packageParams.put("out_trade_no", "wy"+System.currentTimeMillis());
//        packageParams.put("spbill_create_ip", getIpAddr(req));
//        packageParams.put("total_fee", "1");
//        packageParams.put("trade_type", "JSAPI");
//        packageParams.put("openid", userInfo.getString("openid"));
//        String sign = WXPayUtil.generateSignature(packageParams,  WXConstants.KEY);
//        packageParams.put("sign", sign);
//
//        System.err.println("请求参数:"+JSON.toJSONString(packageParams));
//        String xml = WXPayUtil.mapToXml(packageParams);//将所有参数(map)转xml格式
//
//        System.err.println("检查签名:"+WXPayUtil.generateSignature(packageParams,WXConstants.KEY, WXPayConstants.SignType.MD5));
//
//        // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
//        String unifiedorder_url ="https://api.mch.weixin.qq.com/pay/unifiedorder";
//
//        String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id
//        System.err.println("获取到的URL:"+xmlStr);
//        //以下内容是返回前端页面的json数据
//        String prepay_id = "";//预支付id
//        if (xmlStr.indexOf("SUCCESS") != -1) {
//            Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlStr);
//            String appId = (String) resultMap.get("appid");//微信公众号AppId
//            String timeStamp = WXPayUtil.getCurrentTimestamp()+"";//当前时间戳
//            String prepayId = "prepay_id="+resultMap.get("prepay_id");//统一下单返回的预支付id
//            String nonceStr = WXPayUtil.generateNonceStr();//不长于32位的随机字符串
//            Map<String,String> signMap = new TreeMap<>();//自然升序map
//            signMap.put("appId",appId);
//            signMap.put("package",prepayId);
//            signMap.put("timeStamp",timeStamp);
//            signMap.put("nonceStr",nonceStr);
//            signMap.put("signType","MD5");
//            model.addAttribute("appId",appId);
//            model.addAttribute("timeStamp",timeStamp);
//            model.addAttribute("nonceStr",nonceStr);
//            model.addAttribute("prepayId",prepayId);
//            String paySign = WXPayUtil.generateSignature(signMap, WXConstants.KEY);
//            model.addAttribute("paySign",paySign);//获取签名
//            System.err.println("返回的参数:"+JSON.toJSONString(signMap));
//        }

        return "/order";
    }




    /**
     * 获取当前网络ip
     * @param request
     * @return
     */
    public String getIpAddr(HttpServletRequest request){
        String ipAddress = request.getHeader("x-forwarded-for");
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
                //根据网卡取本机配置的IP
                InetAddress inet=null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress= inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
            if(ipAddress.indexOf(",")>0){
                ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }
}
